package com.mes.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageInfo;
import com.mes.biz.domain.BizProduct;
import com.mes.biz.domain.BizProductCategory;
import com.mes.biz.domain.BizWarehouse;
import com.mes.biz.domain.BizWarehouseSpace;
import com.mes.biz.domain.vo.ImportProduct;
import com.mes.biz.domain.vo.ProductVo;
import com.mes.biz.mapper.BizProductMapper;
import com.mes.biz.service.BizProductCategoryService;
import com.mes.biz.service.BizProductService;
import com.mes.biz.service.BizWarehouseService;
import com.mes.biz.service.BizWarehouseSpaceService;
import com.mes.common.constant.Constants;
import com.mes.common.core.domain.AjaxResult;
import com.mes.common.core.domain.BaseEntity;
import com.mes.common.core.domain.TreeNode;
import com.mes.common.core.domain.entity.SysUser;
import com.mes.common.core.service.BaseServiceImpl;
import com.mes.common.exception.BizException;
import com.mes.common.exception.CustomException;
import com.mes.common.utils.StringUtils;
import com.mes.system.common.SysErrorCode;
import com.mes.system.domain.SysConfig;
import com.mes.system.strategy.AutoCodeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UnknownFormatConversionException;

/**
 * 产品Service业务层处理
 * @author hwg
 * @email hwg
 * @date 2023-04-02
 */
@Service
@Transactional(readOnly = true)
public class BizProductServiceImpl extends BaseServiceImpl<BizProductMapper, BizProduct> implements BizProductService {

    private static final Logger log = LoggerFactory.getLogger(BizProductServiceImpl.class);
    @Resource
    private BizProductCategoryService bizProductCategoryService;
    @Resource
    private BizWarehouseService bizWarehouseService;
    @Resource
    private AutoCodeUtil autoCodeUtil;
    @Resource
    private BizProductMapper bizProductMapper;
    @Resource
    private BizWarehouseSpaceService bizWarehouseSpaceService;
    /**
     * 获取单条数据
     * @param bizProduct 产品
     * @return 产品
     */
    @Override
    public BizProduct get(BizProduct bizProduct) {
        BizProduct dto = super.get(bizProduct);
        return dto;
    }

    /**
     * 获取单条数据
     * @param id 产品id
     * @return 产品
     */
    @Override
    public BizProduct get(String id) {
        BizProduct dto = super.get(id);
        return dto;
    }

    /**
     * 查询产品列表
     * @param bizProduct 产品
     * @return 产品
     */
    @Override
    public List<BizProduct> findList(BizProduct bizProduct) {
		List<BizProduct> bizProductList = super.findList(bizProduct);
        return bizProductList;
    }

    /**
     * 分页查询产品列表
     * @param bizProduct 产品
     * @return 产品
     */
    @Override
    public PageInfo<BizProduct> findPage(BizProduct bizProduct) {
		PageInfo<BizProduct> page = super.findPage(bizProduct);
        if (!CollectionUtils.isEmpty(page.getList())) {
            page.getList().stream().forEach(dto -> {
                if (StringUtils.isNotEmpty(dto.getCategoryId())){
                    BizProductCategory category = bizProductCategoryService.get(dto.getCategoryId());
                    if (null != category){
                        dto.setCategoryName(category.getCategoryName());
                    }
                }
                if(StringUtils.isNotEmpty(dto.getWarehouseId())) {
                    BizWarehouse warehouse = bizWarehouseService.get(dto.getWarehouseId());
                    if(null!=warehouse) {
                        dto.setWarehouseName(warehouse.getWarehouseName());
                    }
                }
            });
        }
        return page;
    }

    /**
     * 保存产品
     * @param bizProduct
     * @return 结果
     */
    @Override
    public boolean save(BizProduct bizProduct) {
        return super.save(bizProduct);
    }

    /**
     * 删除产品信息
     * @param bizProduct
     * @return 结果
     */
    @Override
    public boolean remove(BizProduct bizProduct) {
        return super.remove(bizProduct);
    }

    /**
     * 批量删除产品
     * @param ids 需要删除的产品ID
     * @return 结果
     */
    @Transactional(readOnly = false)
    @Override
    public int deleteBizProductByIds(String[] ids) {
        if (ids !=null){
            for (String id :ids){
                //判断是否存在单据明细中
                BizProduct bizProduct = super.get(id);
                long l = bizProductMapper.checkInDetailByProductId(bizProduct.getId(), bizProduct.getProductCode());
                if (l>0){
                    throw new BizException("产品编号"+bizProduct.getProductCode()+"已存在单据中，不能删除");
                }
            }
        }
        return mapper.deleteBizProductByIds(ids, BaseEntity.DEL_FLAG_DELETE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createProduct(BizProduct bizProduct) {
        //根据产品分类处理
       BizProductCategory  productCategory =  bizProductCategoryService.get(bizProduct.getCategoryId());
       String serialCode = null;
        String prefix = PinyinUtil.getFirstLetter(productCategory.getCategoryName(),"").toUpperCase();
        serialCode = autoCodeUtil.genSerialCode("PRODUCT_CODE",prefix);
        bizProduct.setProductCode(serialCode);
        return save(bizProduct);
    }


    /**
     * 构建前端所需要树结构
     * @param level    展开层级
     * @param parentId 父节点ID
     * @return
     */
    @Override
    public List<TreeNode> buildTree(int level, String parentId){
        BizProduct bizProduct = new BizProduct();
        bizProduct.setId(StringUtils.EMPTY);
        return this.buildTreeDataExcludeChild(level, parentId, bizProduct);
    }

    /**
     * 递归构建前端所需要树结构
     * @param level     展开层级
     * @param parentId  父节点ID
     * @param excludeBizProduct 排除节点信息
     * @return
     */
    @Override
    public List<TreeNode> buildTreeDataExcludeChild(int level, String parentId, BizProduct excludeBizProduct) {
        List<TreeNode> listData = new ArrayList<TreeNode>();
        level--;
        BizProduct bizProduct = new BizProduct();
        bizProduct.setParentId(parentId);
        List<BizProduct> bizProductList = mapper.findTreeList(bizProduct);
        for (BizProduct product : bizProductList) {
            //叶子节点处理和level处理
            if(product.getNodeType().equals("2")) {
                product.setTreeLeaf("y");
                continue;
            }
            BizProduct subProduct = new BizProduct();
            subProduct.setParentId(parentId);
            List<BizProduct> subProductList = mapper.findTreeList(subProduct);
            if(!subProductList.isEmpty()) {
                product.setTreeLeaf("n");
            }
        }
        for (BizProduct product : bizProductList) {
            if (!product.getId().equals(excludeBizProduct.getId())) {
                TreeNode treeNode = this.convertTreeNodeData(product);
                if ("n".equals(product.getTreeLeaf()) && level != 0) {
                    treeNode.setChildren(this.buildTreeDataExcludeChild(level, product.getId(), excludeBizProduct));
                } else {
                    treeNode.setChildren(null);
                }

                //判断父节点的加好是否需要展开：如果没有兄弟节点，则该父节点收起来
                if(product.getId().equals(excludeBizProduct.getParentId())){
                    if (org.apache.commons.collections.CollectionUtils.isEmpty(treeNode.getChildren())) {
                        treeNode.setIsLeaf(true);
                    }
                }

                //不展开节点的父节点数据处理
                if (org.apache.commons.collections.CollectionUtils.isEmpty(treeNode.getChildren())) {
                    treeNode.setChildren(null);
                }
                listData.add(treeNode);
            }
        }
        return listData;
    }

    @Override
    public BizProduct getBizProductByProductCode(String productCode) {
        return bizProductMapper.getBizProductByProductCode(productCode);
    }

    @Override
    public int batchUpdate(ProductVo productVo) {

        return bizProductMapper.batchUpdate(productVo);
    }

    @Override
    public AjaxResult importData(List<ImportProduct> bizProductList,String warehouseId) {
        if (StringUtils.isNull(bizProductList) || bizProductList.size() == 0) {
            throw new CustomException("导入数据不能为空！");
        }
        int failureNum = 0;
        StringBuilder failureMsg = new StringBuilder();
        if (StringUtils.isEmpty(warehouseId)) {
            throw new BizException("仓库不能为空");
        }
        List<ImportProduct> list = new ArrayList<>();
        for (ImportProduct product : bizProductList) {
            if (StringUtils.isNotEmpty(product.getProductCode())) {
                BizProduct bizProduct = getBizProductByProductCode(product.getProductCode());
                if (StringUtils.isNull(bizProduct)) {
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、产品编号 ").append(product.getProductCode()).append("不存在，导入失败");
                } else {
                    BigDecimal number = product.getNumber();
                    BeanUtil.copyProperties(bizProduct, product);
                    product.setNumber(number);
                }
                if (StringUtils.isNotEmpty(product.getUnitName())) {
                    if (product.getUnitName().equals(product.getUnit())) {
                        product.setDefaultOutboundUnit(1);
                    } else if (product.getUnitName().equals(product.getAssistUnitA())) {
                        product.setDefaultOutboundUnit(2);
                    } else if (product.getUnitName().equals(product.getAssistUnitB())) {
                        product.setDefaultOutboundUnit(3);
                    }else{
                        failureNum++;
                        failureMsg.append("<br/>").append(failureNum).append("、产品编号 ").append(product.getProductCode()).append("的单位").append(product.getUnitName()).append("不存在当前单位中，导入失败");
                    }
                }
                String space = product.getSpace();
                if (StringUtils.isNotEmpty(space)) {
                    BizWarehouseSpace bizWarehouseSpace = bizWarehouseSpaceService.getSpaceIdBySpaceWithWarehouseId(warehouseId, space);
                    if (StringUtils.isNull(bizWarehouseSpace)) {
                        failureNum++;
                        failureMsg.append("<br/>").append(failureNum).append("、产品编号 ").append(product.getProductCode()).append("的仓位").append(product.getSpace()).append("不存在当前仓库中，导入失败");
                    } else {
                        product.setSpaceId(bizWarehouseSpace.getId());
                    }
                }
                product.setRemark(product.getImportRemark());
                list.add(product);
            } else {
                throw new BizException("产品编号不能为空");
            }
            if (failureNum > 0) {
                failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
                return AjaxResult.error(500,failureMsg.toString());
            }
        }
        return AjaxResult.success(list);
    }

    @Override
    public void checkDataUnique(BizProduct bizProduct) {
        BizProduct product=new BizProduct();
        product.setNotEqualId(bizProduct.getId());
        product.setBrand(bizProduct.getBrand());
        product.setColor(bizProduct.getColor());
        product.setSpec(bizProduct.getSpec());
        product.setModel(bizProduct.getModel());
        if (!CollectionUtils.isEmpty(mapper.findListWithUnique(product))) {
            throw new BizException("已存在相同品牌、颜色、规格、型号的商品");
        }
    }

    /**
     *  构建树形结构
     * @param entityNodes 节点集合
     * @return List<VueNode>
     */
    private List<TreeNode> createTreeData(List<BizProduct> entityNodes) {
        List<TreeNode> list = convertTreeNodeDatas(entityNodes);
        List<TreeNode> treeList = new ArrayList<TreeNode>();
        for (TreeNode treeNode : list) {
            //找到根节点
            if (Constants.TREE_ROOT.equals(treeNode.getParentId())) {
                treeList.add(treeNode);
            }
            List<TreeNode> children = new ArrayList<TreeNode>();
            //再次遍历list，找到子节点
            for (TreeNode node : list) {
                if (node.getParentId().equals(treeNode.getId())) {
                    children.add(node);
                }
            }
            treeNode.setChildren(children);
        }
        return treeList;
    }

    /**
     * 转换前端树节点
     * @param listData 树表格数据
     * @return
     */
    private List<TreeNode> convertTreeNodeDatas(List<BizProduct> listData) {
        List<TreeNode> treeNodes = new ArrayList<TreeNode>();
        for (BizProduct node : listData) {
            TreeNode treeNode = convertTreeNodeData(node);
            treeNodes.add(treeNode);
        }
        return treeNodes;
    }

    /**
     * 将实体类转化成前端对象格式
     * @param node 树表格对象
     * @return
     */
    private TreeNode convertTreeNodeData(BizProduct node) {
        TreeNode treeNode = new TreeNode();
        treeNode.setId(node.getId());
        treeNode.setKey(node.getId());
        treeNode.setTitle(node.getNodeName());
        treeNode.setLabel(node.getNodeName());
        treeNode.setSelectable(true);
        treeNode.setDisabled(false);
        treeNode.setDisableCheckbox(false);
        treeNode.setParentId(node.getParentId());
       /* treeNode.setParentIds(node.getParentIds());*/
        HashMap<String,Object> attr = new HashMap<>();
        attr.put("treeLeaf", node.getTreeLeaf());
       /* attr.put("treeLevel", node.getTreeLevel());
        attr.put("treePath", node.getParentIds());*/
        treeNode.setAttributes(attr);
        treeNode.setIsLeaf(Constants.TREE_LEAF_Y.equals(node.getTreeLeaf()) ? true : false);
        JSONObject slotsValue = new JSONObject();
        treeNode.setSlots(slotsValue);
        JSONObject scopedSlotsValue = new JSONObject();
        scopedSlotsValue.put("title","title");
        treeNode.setScopedSlots(scopedSlotsValue);
        return treeNode;
    }

}
